package io.libp2p.example.localserver;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import io.libp2p.example.chat.MyLog;
import io.libp2p.example.chat.OpenUtils;


public class FileServer extends NanoHTTPD {

    private static String TAG = "NanoHTTPD";

    // M3u8Server 服务对象
    private static NanoHTTPD mM3u8Server;
    // 端口号
    public static final int PORT = 13121;

    private Context context;

    /**
     * 构造方法
     */
    public FileServer(Context context) {
        // 端口号
        super(PORT);

        this.context = context;
    }


    /**
     * 启动服务
     */
    public static void execute(Context context) {
        if(mM3u8Server != null && mM3u8Server.isAlive()) return;

        Log.d(TAG, "---execute---");
        try {
            // 创建服务
            mM3u8Server = new FileServer(context);
            // 超时时间
            mM3u8Server.start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);

            Log.i(TAG, "服务启动成功\n");
        } catch (IOException ioe) {
            Log.e(TAG, "启动服务失败：\n" + ioe);
            //System.exit(-1);
        } catch (Exception e) {
            Log.e(TAG, "启动服务失败：\n" + e);
            //System.exit(-1);
        }


    }

    /**
     * 关闭服务
     */
    public static void finish() {
        Log.d(TAG, "---finish---");
        if (mM3u8Server != null) {
            mM3u8Server.stop();
            Log.i(TAG, "服务已经关闭");
            mM3u8Server = null;
        }
    }


    /**
     * 重写 serve 方法，获取本地sdcard视频文件
     *
     * @param session The HTTP session
     * @return
     */
    @Override
    public Response serve(IHTTPSession session) {
        Log.d(TAG, "---server---");

        Map<String, String> headerMap = session.getHeaders();

        for(Map.Entry<String, String> entry : headerMap.entrySet()){
            Log.e(TAG, "请求Header "+entry.getKey()+"="+entry.getValue());
        }

        //
        String url = String.valueOf(session.getUri());
        Log.d(TAG, "请求URL：" + url);
        File file = new File(url);
        //
        if (file.exists()) {
            FileInputStream fis;

            try {
                fis = new FileInputStream(file);
            } catch (Exception e) {
                e.printStackTrace();
                return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/html", createDefaultRsp(headerMap));
            }

            long length = file.length();
            long start = getRange(headerMap.get("range"));
            long end = length - 1;

            try {
                fis.skip(start);
            } catch (Exception e) {
                start = 0;
                MyLog.W(TAG, "range skip IOException:"+e);
            }

            if(start > 0){
                long contentLength = length - start;

                Response response = newFixedLengthResponse(Response.Status.PARTIAL_CONTENT, getMimeTypeFromFile(file), fis, contentLength);
                response.addHeader("Content-Length", String.valueOf(contentLength));
                response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + length);
                response.addHeader("Accept-Ranges", "bytes");

                return response;
            }else{
                return newFixedLengthResponse(Response.Status.OK, getMimeTypeFromFile(file), fis, length);
            }

        } else {
            return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/html", createDefaultRsp(headerMap));
        }
    }

    private String getMimeTypeFromFile(File file) {
        String fileName = file.getName();

        String mimeType = "*/*";

        if (fileName.endsWith(".jpg") || fileName.endsWith(".png")) {
            mimeType = "image/jpeg";
        } else if (fileName.endsWith(".mp4") || fileName.endsWith(".mkv") || fileName.endsWith(".avi")) {
            mimeType = "video/mp4";
        }

        return mimeType;
    }

    private String createDefaultRsp(Map<String, String> header){
        StringBuilder builder = new StringBuilder();

        builder.append("<p>");
        builder.append("最近的20个媒体文件:");
        builder.append("<br>");

        String host = "http://"+header.get("host");

        List<String> list = OpenUtils.loadRecentMedia(context);

        for(String path: list){
            String link = host + path;
            String html = String.format("<a href=\"%s\">%s</a>\r\n", link, new File(path).getName());

            builder.append(html);

            builder.append("<br>");
        }

        builder.append("</p>");

        return builder.toString();
    }

    public static long getRange(String range){
        long start = 0;

        if(range != null && range.startsWith("bytes=")){
            String bytes = range.substring(6);

            if(!bytes.startsWith("-")){
                String split[] = bytes.split("-");
                if(split.length > 0 && !TextUtils.isEmpty(split[0])){
                    start = Long.parseLong(split[0]);
                }

                MyLog.D(TAG, "getRange bytes="+bytes+",start="+start);
            }

        }else{
            MyLog.D(TAG, "getRange is empty range="+range);
        }

        return start;
    }
}
